#!/usr/bin/python
# -*- coding: utf-8 -*-

import ConfigParser

from xmpp import *
import time,os,time,sys
import random

VERSION = u'0.0.7'

CHANGELOG = u'''Журнал изменений dotBot'a:
0.0.7
	+ Для Maxidax'a добавлен краткий вызов развлекалова, те !b - бор,!a - анек,!o - острие,!p - погода. Точно также и русские буквы поддерживаются, те !б,!а,!о,!п - погода.
	+ Добавлена команда !topic, которая устанавливает одинаковый топик во всех каналах.
	+ Добавлен алиас на команду !kick, теперь ее можно вызывать и как !kill
0.0.6
	+ Переделана ошибка генерации фраз с bash.org.ru, исчезла переменная max_bor
	+ Добавлены анекдоты с http://ostrie.moskva.com.
	+ Теперь приход-уход юзерей из чата отображается как статус сообщения (требовал maxidax).
0.0.5
	+ Исправлена ошибка связанная с падением бота при нулевом тексте
	+ При полном слете бота работает реконект (спасибо nVa)
	! Легкий редизайн кода, в направлении увеличения скорости...
	+ Исправлена ошибка связанная с закрытием лог файлов.
	+ Теперь бот обознает команды такого же бота и не транслирует линки между тамими же ботами
	+ Добавлена возможность считать болтунов в канале.
	! Полностью изменена процедура обработки конфига !!! В связи с этим изменился сам конфиг, теперь адрес канала идет в заголовке секции и необходим только ник !
	+ Добавлена команда !save, которая сохраняет накопленные данные в конфиге, выполнять ее могут только супер-админы.
	+ Добавлена опция вывода анекдотов, беруться из http://best-aneks.com/rss.php.
	+ Добавлена опция получения погоды, для запроса надо написать по-русски имя города, например !pogoda москва. Погода и города беруться с gismeteo.ru.
	+ Добавлена опция вывода компутерныйх фраз с http://bash.org.ru.
	+ Добавлена команда пересоединения к конференциям.
	+ Теперь бот всегда сохраняет конфиг при выходе.
	! Теперь при "замученом" канале в канал не падают оповещения, спасибо maxidax.
	! Исправлена ошибка в только что созданной команде !bor, спасибо maxidax.
	+ Полный лист изминений тепеь могут получить только админы, остальные пусть довольствуются последней  версией :)
	+ Теперь бот выводит крылатые фразы Фоменко.
	+ Добавлен переводчик с русского в энглицкий и обратно.
	+ Добавлена опция установки информации о канале.
	+ Можно (командой !list full) увидеть полный листинг канала, даже если в канеле кроме бота никого нет.
	! Теперь бот бытается войти в канала с доступным именем (если его занято)
	+ Добавлена команда переименования бота в канале
	+ Добавлена опция кика юзера за flood
	+ Админ теперь может менять некоторые переменные и настройки бота (смотри !help:admin)
	! Команда !reconnect заменена на !rejoin, так как "пересоединение" больше похоже на спицифику данной команды
	! Исправил команду переименования бота в каналах
	! Теперь help,help:admin, changelog, changelog all будут посывать свой текст в приват
	! Теперь админы могут кого-нить кильнуть :)
	+ При большом объеме сообщений пересылаемых между каналами бот разбивает сообщение и посылает его порциями с определенной задежкой. На размер разбиваемого сообщения влияет переменная message_split.
	! Исправлен досабный баг, спасибо Лексяра.
	+ Написан небольшой спам модуль, ибо СПАМБОТЫ ЗАДОЛБАЛИ !!!!
0.0.4
	+ Полностью переписана логика работы программы, теперь состояние всех чатов хранится при инициализации
	+ Добавлен команда получения статуса пользователя (берется из presence)
	+ Добавлена возможность конекта по адресу сервера (подсказал LEXUS-911)
	+ Переписана логика команды !list - теперь она основана на presence.
	+ Теперь (если юзер заблокирован командой !block) при листинге (команда !list) у него в конце ника пишется {B}
	+ Для канала находящегося в !mute при листинге добавляется аттрибут {M}
	+ Команда ping и vcard теперь тоже используют накопленные presence, вместо выполнения поиска по каналу
0.0.3
	+++ - наконец-то у бота есть имя - "dotBot" !!!
	+ Добавлена команда Ping.
	+ Добавлена команда получения vCard'ов.
	! Переписана логика программы на объектный манер :)
	+ Теперь работает оповещение о приходе-уходе юзерей из каналов. Оповещение начинает работать через 20 секунд после конекта (или реконекта) к конфе.
	+ Добавлена команда block, которая блокирует Ваш ник для трансфера в другие конфы.
0.0.2
	+ Добавлена возможность запрета трансфера сообщений не имеющих ника (например сообщения канала).
	+ Добавлен реконект при вылете боты из конфы.
	+ Добавлена команда mute.
	+ При включенном логе, не валит экран одно и тоже сообщение.
0.0.1
	+ Просто написал бота, сделал ему нормальный конфиг, пока только линкует каналы (правда сколько угодно :) ).

'''

ADDONS = u'\n\nВерсия dotBot: %s. Смотреть версии на http://sys.net.ru.'%VERSION

HELP = u'''Итак, помошчь... :)
Доступные команды:
	!help - собственно ентот текст
	!help:admin - помощь для админов
	!changelog - данные о последней версии бота
	!me <любая фраза> - вывод любого текста в остальные линкованные каналы
	!list <full> - вывод списка в линкованных каналах (бот себя не пишет в список). При использовании оции full - выводит вообче данную обо всех линкованных каналах.
	!ping <ник юзера> - послать пинг и получить pong
	!vcard <ник юзера> - получить vCard пользователя
	!mute - запрещает транслящию в данный канал на некоторое время, повторное использование команды разрешает трансляцию до истечения времени
	!block - блокирует Ваш ник для отправки сообщений в другие конференции
	!status <ник юзера> - получение статуса пользователя
	!talkers - выводит список балтунов в канале
	!anek - Получить свеженький анекдот
	!pogoda <имя города по-русски> - получить погоду для выбранного города
	!bor - Следующий афоризм с http://bash.org.ru
	!ostrie - Анекдоты и истории с сайта http://ostrie.moskva.com
	!fomenko - Выводит крылатые фразы Фоменко
	!tr <направление> <фраза для перевода> - переводчик, направление это: er - энглицко-русский, re-русско энглицкий.
	!info - выдает информацию о данном канале

'''

ADMIN_HELP = u'''Помощь для админов...
Доступные команды:
	!help:admin - вот ентот текст
	!changelog:all - список ВСЕХ моих изменений, доступно только админам
	!save - сохранение данных, только для супер админов
	!rejoin - Пересоединение ко всем конференциям, доступно только для админов
	!kick <ник> - киляние юзера
	!admin:add <Jid> - Добавление Jid в админы, доступно только супер админам
	!admin:del <Jid> - Удаление Jid из админов, доступно только супер админам
	!channel:add <канал@сервер/ник> - добавление бота в канал, если ник опущен, то именуем точкой :) Доступно админами
	!channel:del <канал@сервер> - убрать бота из канала, доступно админам
	!channel:nick <канал@сервер/><новый ник> - установить ник бота для канала, при этом канал и сервер можно опустить, тогда все сработает для текущего канала
	!info:set <канал> <информационная фраза> - устанавливает информацию о канале (если канал опущен - для текущего канала), доступно только админам.
	!var:list - список всех переменных бота
	!var:get <переменная> - текущее значение переменной
	!var:set <переменная> <новое значение> - установка значений переменной
'''


DEFAULT_CFG={
	'GLOBAL:jid':'dotBot@jabber.ru',
	'GLOBAL:time_live':60,
	'GLOBAL:log_to_screen':0,
	'GLOBAL:transfer_no_nickname':0,
}


from config import Config


########################
## Основная программная часть ##
########################

def safe_int(s,default=0):
	try: return int(('%s'%s).split('.')[0])
	except: return default

def skip_space_line(s):
	r = ''
	for x in s.split('\n'):
		xx = x.strip()
		if xx: r+='%s\n'%xx
	return r

def unescape(s):
	cp = 0
	ret = u''
	while True:
		x = s.find('&',cp)
		if x==-1: break
		ret += s[cp:x]
		if s[x+1] == '#' and s[x+2] == 'x' and s[x+7]==';':
			r = chr(eval('0x%s'%s[x+5:x+7]))
			r += chr(eval('0x%s'%s[x+3:x+5]))
			ret += unicode(r,'utf-16')
		cp = x+8
	return ret

class CLASS_LOG:
	'Класс логера'
	def __init__(self,log_folder='logs',on_screen=False):
		if not log_folder.strip(): self.off = True ; return
		else: self.off = False
		self.log_folder = log_folder
		self.on_screen = on_screen
		if not os.path.exists(os.path.realpath(log_folder)):
			try: os.mkdir(os.path.realpath(log_folder))
			except: print 'Error with Create log dir !!!'
		self.spool = {} ## Спул все открытых лог файлов {полный путь до файла:[файловый объект,время открытия файла]}
		self.previos_log_on_screen = ''
	def __call__(self,stanza,nick,text):
		'Основная процедура выбора лога'
		t = time.time()
		for x in self.spool.keys():
			if self.spool[x][1]+25*3600 < t: ## Закрыть ентот файл
				try: self.spool[x][1].close()
				except: print 'Error in close file %s.'%x
				del self.spool[x]
		if self.off: return
		## Создание необходимых директорий и файлов
		ct=time.localtime()
		conference=stanza.getFrom().getStripped().replace('@','%')
		full_dir_name = os.path.realpath(self.log_folder)+'/'+unicode(conference).encode('utf-8')
		full_file_name = '%s/%02d.%02d.%02d.html'%(full_dir_name,ct[0],ct[1],ct[2])
		if not os.path.exists(full_dir_name):
			try: os.mkdir(full_dir_name)
			except:
				print 'Error with Create log dir from %s conference!!!'%conference
				return
		## Создание и обработка файлов
		if self.spool.has_key(full_file_name): ## Уже есть открытый файл
			file = self.spool[full_file_name][0]
		else:
			if os.path.exists(full_file_name): file = open(full_file_name,'a')
			else:
				file = open(full_file_name,'w')
				file.write('<html xml:lang="ru-RU" lang="ru-RU" xmlns="http://www.w3.org/1999/xhtml"><head><meta content="text/html; charset=utf-8" http-equiv="content-type" />')
				file.write('<title>%s logs for %02d.%02d.%02d</title></head><body><table border="1"><tr><th>time</th><th>who</th><th>text</th></tr>'%(conference,ct[0],ct[1],ct[2]))
			self.spool[full_file_name] = (file,time.time())
		## Вывод чегой-та в лог файл
		file.write((u"<tr><td>%02d.%02d.%02d %02d:%02d</td><td>%s</td><td>%s</td></tr>\n"%(ct[0],ct[1],ct[2],ct[3],ct[4],nick,text)).encode('utf-8'))
		file.flush()
		if self.on_screen:
			if self.previos_log_on_screen != text:
				print (u'%02d.%02d.%02d %02d:%02d <%s> %s'%(ct[0],ct[1],ct[2],ct[3],ct[4],nick,text)).encode('utf-8')
				self.previos_log_on_screen = text


def concat(ms,rz=','):
	'Склеивает массив через разредлитель'
	ret = ''
	for x in ms:
		ret += '%s%s'%(x,rz)
	return ret[:-len(rz)]

class clSend:
	'Просто посылает сообщение'
	def __init__(self,sess,vars):
		self.__sess = sess
		self.vars = vars
	def __send__(self,typ,to,text):
		try: message_split = safe_int(self.vars['message_split'])
		except: message_split = 1000
		if message_split==0 or len(text)<=message_split: self.__sess.send(protocol.Message(to,text,typ,attrs={'id':'JBL:MESSAGE'}))
		else:
			cp = 0
			while cp<len(text):
				self.__sess.send(protocol.Message(to,text[cp:cp+message_split],typ,attrs={'id':'JBL:MESSAGE'}))
				cp += message_split
				time.sleep(2)

class clChatSend(clSend):
	'Просто посылает сообщение в чат'
	def __call__(self,to,text):
		self.__send__('groupchat',to,text)

class clPrivateSend(clSend):
	'Просто посылает сообщение в приват'
	def __call__(self,to,nick,text):
		self.__send__('chat','%s/%s'%(to,nick),text)

class clChatList:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,to,id):
		'Послыает в любой канал запрос на листинг юзерей'
		self.__sess.send(u"<iq id='%s' to='%s' type='get'><query xmlns='http://jabber.org/protocol/disco#items'/></iq>"%(id,to))

class clVCard:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,to,id):
		'Запрашивает VCard'
		self.__sess.send(u"<iq to='%s' type='get' id='%s'><vCard xmlns='vcard-temp'/></iq>"%(to,id))

class clPing:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,to,id):
		'Делает пинг на юзера'
		self.__sess.send(u"<iq type='get' to='%s' id='%s'><query xmlns='jabber:iq:version'/></iq>"%(to,id))

class clExit:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,to):
		'Выход из конфы'
		self.__sess.send(u"<presence to='%s' type='unavailable'/>"%to)

class clRename:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,addr,nick):
		'Выход из конфы'
		self.__sess.send(u"<presence to='%s/%s' />"%(addr,nick))

class clSendStatus:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,to,text):
		'Посылка статусного сообщения в конфу'
		self.__sess.send(u"<presence to='%s'><show>xa</show><status>%s</status></presence>"%(to,text))

class clKick:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,addr,nick,message=u'You spammer !!!'):
		'Кик юзера'
		self.__sess.send(u"<iq id='kicker' to='%s' type='set'><query xmlns='http://jabber.org/protocol/muc#admin'><item nick='%s' role='none'><reason>%s</reason></item></query></iq>"%(addr,nick,message))

class clSetTopic:
	def __init__(self,sess,vars):
		self.__sess = sess
		self.__vars = vars
	def __call__(self,addr,topic):
		'Установка нового топика'
		print u"<message id='cm' to='%s' type='groupchat'><subject>%s</subject></message>"%(addr,topic)
		self.__sess.send(u"<message id='cm' to='%s' type='groupchat'><subject>%s</subject></message>"%(addr,topic))



class clCommand:
	def __init__(self,sess,vars):
		self.chatsend = clChatSend(sess,vars)
		self.privatesend = clPrivateSend(sess,vars)
		self.chatlist = clChatList(sess,vars)
		self.vcard = clVCard(sess,vars)
		self.ping = clPing(sess,vars)
		self.exit = clExit(sess,vars)
		self.rename = clRename(sess,vars)
		self.kick = clKick(sess,vars)
		self.settopic = clSetTopic(sess,vars)
		self.chatstatus = clSendStatus(sess,vars)


class cInfo:
	'Класс полностью извлекает все необходимые данные и устанавливает их на себя'
	## nick - Ник отправившего
	## text - сообщение (тело)
	## domain - домайн юзера
	## node - нода сообщения
	## addr - node@domain
	## command - Комманда переданная в сообщении (начинается всегда в !)
	## command_param - Параметры каманды
	def __getattr__(self,name):
		nl = name.lower()
		if self.__dat.has_key(nl): return self.__dat[nl]
		return None
	def __setitem__(self,name,value):
		nl = name.lower()
		self.__dat[nl] = value
	def keys(self):
		return self.__dat.keys()
	def __init__(self,mess,sess,vars={}):
		dat = {}
		dat['id'] = mess.getID()
		dat['command_id'],dat['command_id_param'] = '',[]
		if dat['id']!=None and dat['id'][:4] == 'JBL:': ## Результат команды
			sp = dat['id'][4:].split(':')
			if len(sp)>=1:
				dat['command_id'] = '%s'%sp[0].lower()
				dat['command_id_param'] = sp[1:]
		try: dat['nick'] = mess.getFrom().getResource()
		except:  dat['nick'] = u''
		try: dat['text'] = u'%s'%mess.getBody()
		except:  dat['text'] = u''
		if dat['text']==None: dat['text'] = u''
		dat['type'] = mess.getType()
		dat['domain'] = mess.getFrom().getDomain()
		dat['node'] = mess.getFrom().getNode()
		dat['addr'] = u'%s@%s'%(dat['node'],dat['domain'])
		dat['jid'] = u'%s/%s'%(dat['addr'],dat['nick'])
		if len(dat['text'])>1 and dat['text'][0]==u'!':
			ps = (dat['text']+' ').index(' ')
			dat['command'] = unicode(dat['text'][:ps]).strip().lower()
			dat['command_param'] = dat['text'][ps+1:].strip()
		else: dat['command'],dat['command_param'] = '',''
		dat['com'] = clCommand(sess,vars)
		try: dat['status'] = mess.getStatus().strip()
		except: dat['status'] = ''
		self.__dat = dat
	def xx(self):
		print self.__dat


class clVars:
	vars = {
		'flood_kick': (2,u'На каком одинаковом сообщении кикать юзера'),
		'flood_message': (u'Флудерастам тут не место...',u'Сообщение при кике за флуд'),
		'mute_time':(1800,u'Максимальное время "замученности" канала'),
		'message_split':(1000,u'Размер разбиения любого длинного сообщения'),
		'spam_char_repeat':(7,u'Максимальное число одинаковых букв идущих друг за другом'),
		'spam_word_len':(20,u'Максимальная длинна слова'),
	}
	def __init__(self,cnf):
		self.cnf = cnf
	def __getitem__(self,itm):
		i = itm.lower().strip()
		if not self.vars.has_key(i): return None
		return self.cnf.get('global:%s'%i,self.vars[i][0])
	def __setitem__(self,itm,vl):
		i = itm.lower().strip()
		if not self.vars.has_key(i): return
		self.cnf['global:%s'%i] = vl
	def keys(self):
		return self.vars.keys()
	def desc(self,itm):
		i = itm.lower().strip()
		return self.vars.get(i,[None,None])

class cl_dotBot:
	'Класс используется для облегчения многих функций'

	def __init__(self,CONFIG):
		self.conf = CONFIG
		self.roster = []
		self.users_state = {} ## Данные обо всех юзерях
		self.presence = {} ## Все соединения с базой (словарь объектов)
		self.kick = {} ## Словарь для кика одних и тех же сообщений от одного и того же юзера
		self.vars = clVars(CONFIG) ## Установим класс с переменными

	def connect(self):
		'Вся процедура конекта'
		self.client=Client(JID(self.conf['global:jid']).getDomain(),debug=[])
		proxy = {}
		if self.conf.get('proxy:host',None):
			proxy['host'] = self.conf['proxy:host']
			proxy['port'] = self.conf['proxy:port']
			proxy['username'] = self.conf['proxy:username']
			proxy['password'] = self.conf['proxy:password']
		self.client.connect(server=self.conf.get('global:direct_connect',None),proxy=proxy)
		self.client.RegisterHandler('message',self.messageCB)
		self.client.RegisterHandler('presence',self.presenceCB)
		self.client.RegisterHandler('iq',self.iqCB)
		self.client.auth(JID(self.conf['global:jid']).getNode(),self.conf.get('global:password',None))
		self.rejoin()
	
	def rejoin(self):
		## Циклическая процедура входа на каналы
		for conf_name in self.conf.sections():
			if self.conf.has_key('%s:nick'%conf_name): ## Это описание конфы - юзаем
				self.confJoin(conf_name)
				self.client.send(self.presence[conf_name])

	def confJoin(self,conf_name):
		'Присоединение к конфе'
		self.presence[conf_name]=Presence(to=u'%s/%s'%(conf_name,self.conf['%s:nick'%conf_name]))
		self.presence[conf_name].setTag('x',namespace=NS_MUC).setTagData('password',self.conf.get('%s:password'%conf_name,None))
		self.presence[conf_name].getTag('x').addChild('history',{'maxchars':'0','maxstanzas':'0'})
		self.conf['%s:connect_time'%conf_name] = time.time()

	def is_superAdmin(self,jid):
		try:
			super_admins = self.conf.get('global:super_admins','').split(',')
			if jid.lower() in super_admins: return True
			else: return False
		except: return False

	def is_Admin(self,jid):
		try:
			admins = self.conf.get('global:admins','').split(',')
			if jid.lower() in admins: return True
			else: return False
		except: return False
	
	def is_Mute(self,dat,chn_id):
		'Проверка на замученность канала :)'
		## Текущее время замучения, если 0 - канал не замучен
		cm = safe_int(self.conf.get('%s:mute'%chn_id,0))
		if cm==0: return False ## Канал не замучен :)
		## Время умалчиваемого замучения
		gm = safe_int(self.vars['mute_time'])
		if cm+gm > time.time(): return True ## Канал был замучен, но теперь надо размутить
		del self.conf['%s:mute'%chn_id]
		dat.com.chatsend(chn_id,'MUTE OFF')
		return False

	def is_Blocked(self,user_jid):
		'Проверка на заблоченность юзера'
		if not self.users_state.has_key(user_jid): return False
		if self.users_state[user_jid].get('blocked',False): return True
		return False

	def reactor(self):
		'Циклический реактор'
		autosave = safe_int(self.conf.get('global:autosave','3600'),3600)
		autosave_count = 0
		while 1:
#			autosave_count += 1
#			self.client.Process(1)
			try: self.client.Process(1)
			except KeyboardInterrupt: sys.exit(0) ## Выход по клаве
			except:
				print '[ERROR] Except in Main Procedure -> rejoin.'
				try: self.client.disconnect()
				except: pass
				del self.client
				time.sleep(3)
				self.connect()
			if autosave_count>= autosave:
				self.conf.save()
				autosave_count = 0

	def messageCB(self,sess,mess):
		'Основная процедура реакции на сообщение'
		## Получим данные о сообщении
		dat = cInfo(mess,sess,self.vars)
		## Начинаем процедуру обработки
		if self.conf['global:transfer_no_nickname']!='1' and (dat.text=='' or dat.nick==''): pass ## Запрет трасфера пустых ников
		elif dat.command_id!=u'JBL:MESSAGE'and  dat.addr in self.conf.sections() and dat.nick != self.conf['%s:nick'%dat.addr]: ## Есть такой канал и не сам себе говорю
			if dat.command == u'!list': self.messageCB_list(dat)
			elif dat.command == u'!me': self.messageCB_me(dat)
			elif dat.command == u'!help': self.messageCB_help(dat)
			elif dat.command == u'!help:admin': self.messageCB_help_admin(dat)
			elif dat.command == u'!changelog': self.messageCB_changelog(dat)
			elif dat.command == u'!changelog:all': self.messageCB_changelog_all(dat)
			elif dat.command == u'!vcard': self.messageCB_vcard(dat)
			elif dat.command == u'!ping': self.messageCB_ping(dat)
			elif dat.command == u'!mute': self.messageCB_mute(dat)
			elif dat.command == u'!block': self.messageCB_block(dat)
			elif dat.command == u'!status': self.messageCB_status(dat)
			elif dat.command == u'!talkers': self.messageCB_talkers(dat)
			elif dat.command in (u'!anek',u'!a',u'!а'): self.messageCB_anek(dat)
			elif dat.command == u'!save': self.messageCB_save(dat)
			elif dat.command in (u'!pogoda',u'!p',u'!п'): self.messageCB_pogoda(dat)
			elif dat.command in (u'!bor',u'!b',u'!б'): self.messageCB_bor(dat)
			elif dat.command in (u'!ostrie',u'!o',u'!о'): self.messageCB_ostrie(dat)
			elif dat.command == u'!fomenko': self.messageCB_fomenko(dat)
			elif dat.command == u'!tr': self.messageCB_tr(dat)
			elif dat.command == u'!rejoin': self.messageCB_rejoin(dat)
			elif dat.command == u'!admin:add': self.messageCB_admin_add(dat)
			elif dat.command == u'!admin:del': self.messageCB_admin_del(dat)
			elif dat.command == u'!var:list': self.messageCB_var('list',dat)
			elif dat.command == u'!var:get': self.messageCB_var('get',dat)
			elif dat.command == u'!var:set': self.messageCB_var('set',dat)
			elif dat.command == u'!channel:add': self.messageCB_channel_add(dat)
			elif dat.command == u'!channel:del': self.messageCB_channel_del(dat)
			elif dat.command == u'!channel:nick': self.messageCB_channel_nick(dat)
			elif dat.command == u'!info': self.messageCB_info(dat)
			elif dat.command == u'!info:set': self.messageCB_info_set(dat)
			elif dat.command in (u'!kick', u'!kill'): self.messageCB_kick(dat)
			elif dat.command == u'!topic': self.messageCB_topic(dat)
			else: self.messageCB_transfer(dat)
		LOG(mess,dat.nick,dat.text)
	
	def messageCB_save(self,dat):
		'Сохранение конфига'
		try: 
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid):
				self.conf.save()
				dat.com.chatsend(dat.addr,u'Конфиг файл сохранен.')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)


	def messageCB_channel_add(self,dat):
		'Добавление бота в канал'
		try: 
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid) or self.is_Admin(jid):
				ca = dat.command_param.strip().split('/')
				if len(ca)==1: channel,nick = ca[0],'.'
				elif len(ca)==2 and ca[1].strip(): channel,nick = ca[0],ca[1].strip()
				else: channel=None
				if channel:
					self.conf['%s:nick'%channel] = nick
					self.conf.save()
					self.rejoin()
					dat.com.chatsend(dat.addr,u'dotBot будет видеть на %s под ником %s.'%(channel,nick))
				else: dat.com.chatsend(dat.addr,u'Както вы не реально канал задали :)')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)


	def messageCB_channel_del(self,dat):
		'Удаление бота из канала'
		try: 
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid) or self.is_Admin(jid):
				ca = dat.command_param.strip()
				if self.conf.get('%s:nick'%ca):
					dat.com.exit('%s/%s'%(ca,self.conf['%s:nick'%ca]))
					for x in self.conf.options(ca):
						del self.conf['%s:%s'%(ca,x)]
					del self.presence[ca]
					self.conf.save()
					self.rejoin()
					dat.com.chatsend(dat.addr,u'dotBot ушел из канала %s.'%ca)
					## Удаление ненужных userstate
					for key in self.users_state.keys():
						conf,nick = key.split('/',1)
						if conf.lower()==ca: del self.users_state[key]
				else: dat.com.chatsend(dat.addr,u'Както вы не реально канал задали :)')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)

	def messageCB_channel_nick(self,dat):
		'Переникование бота в канале'
		try: 
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid) or self.is_Admin(jid):
				ca = dat.command_param.strip().split('/',1)
				if len(ca)==2 and ca[1].strip() and self.conf.get('%s:nick'%ca[0],None): ## Есть такой канал
					self.conf['%s:nick'%ca[0]] = ca[1].strip()
					dat.com.rename(ca[0],ca[1])
				elif ca[0].strip():
					self.conf['%s:nick'%dat.addr] = ca[0].strip()
					dat.com.rename(dat.addr,ca[0])
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)

	def messageCB_admin_add(self,dat):
		'Добавление админа'
		try:
			add_jid = dat.command_param.strip()
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid):
				if self.is_Admin(add_jid): dat.com.chatsend(dat.addr,u'Такой админ то уже есть :).')
				else:
					oo = self.conf.get('global:admins','').strip()
					if oo: self.conf['global:admins'] = '%s,%s'%(oo,add_jid)
					else: self.conf['global:admins'] = add_jid
					self.conf.save()
					dat.com.chatsend(dat.addr,u'Админ добавлен.')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)

	def messageCB_admin_del(self,dat):
		'Удаление админа'
		try:
			del_jid = dat.command_param.strip().lower()
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid):
				if not self.is_Admin(del_jid): dat.com.chatsend(dat.addr,u'Дык нету такого админа :).')
				else:
					ret = ''
					for x in self.conf.get('global:admins','').split(','):
						xx = x.lower().strip()
						if xx != del_jid: ret+='%s,'%xx
					if ret: self.conf['global:admins'] = ret
					else: del self.conf['global:admins']
					self.conf.save()
					dat.com.chatsend(dat.addr,u'Админ удален.')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)


	def messageCB_rejoin(self,dat):
		'Переконекчивание ко всем конфами'
		try: 
			jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
			if self.is_superAdmin(jid) or self.is_Admin(jid):
				self.rejoin()
				dat.com.chatsend(dat.addr,u'Пересоединение к конференциям выполнено.')
			else: dat.com.chatsend(dat.addr,u'Извини дорогой %s, до админа еще надо дорасти.'%dat.nick)
		except: dat.com.chatsend(dat.addr,u'Извини дорогой %s, но определить твой истинный Jid я чего-та не могу :(.'%dat.nick)

	def messageCB_info(self,dat):
		'Вывод инфы о канале'
		info = self.conf.get('%s:info'%dat.addr,None)
		if not info: dat.com.chatsend(dat.addr,u'А не установили инфу для данного канала :)')
		else: dat.com.chatsend(dat.addr,info.replace('\\n','\n'))

	def messageCB_info_set(self,dat):
		'Установка инфы о канале'
		jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
		if self.is_superAdmin(jid) or self.is_Admin(jid):
			info = dat.command_param.strip().replace('\n','\\n')
			i = info.split(' ',1)
			if self.conf.get('%s:nick'%i[0].strip().lower(),None):
				ch = i[0].strip().lower()
				if len(i)==2: info = i[1]
				else: info = ''
			else: ch = dat.addr
			if info: self.conf['%s:info'%ch] = info
			else: del self.conf['%s:info'%ch]


	def messageCB_var(self,cm,dat):
		'Работа с переменными'
		try: jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
		except: jid = None
		if self.is_superAdmin(jid) or self.is_Admin(jid):
			if cm=='list': ## Список переменных
				ret = u'Переменные:\n'
				for x in self.vars.keys():
					y,z = self.vars.desc(x)
					ret += u'\t%s: %s [по-умолчанию:"%s", сейчас:"%s"]\n'%(x,z,y,self.vars[x])
				dat.com.chatsend(dat.addr,ret)
			elif cm=='get': ## Возвращает значение переменной
				vl = self.vars[dat.command_param]
				if vl: dat.com.chatsend(dat.addr,u'%s= %s'%(dat.command_param,vl))
				else: dat.com.chatsend(dat.addr,u'Нет такой переменной...')
			elif cm=='set': ## Установка значения переменной
				v = dat.command_param.split(' ',1)
				if len(v): self.vars[v[0]] = v[1]

	def verifySpam(self,s):
		'Проверяет на спам'
		spam_char_repeat = safe_int(self.vars['spam_char_repeat'])
		spam_word_len = safe_int(self.vars['spam_word_len'])
		## Проверка на 7 повторений одного и того же символа
		char,char_count = '_',0
		word_len = 0
		for x in s:
			if x in [' ','_',',','"',",",'-','=','#','@',':','/','\\']: word_len=0
			else: word_len+=1
			if x==char: char_count+=1
			if spam_char_repeat!=0 and char_count==spam_char_repeat: return True ## Спам за повторения одной и тойже буквы
			if spam_word_len!=0 and word_len==spam_word_len: return True ## Слишком длинное слово
			char = x
		return False

	def messageCB_transfer(self,dat):
		'Раскидывает все сообчений по чатам'
		## Попытка вычисления текущего jid юзера
		try: jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
		except: jid = None
		## Подсчет челов которые много болтают
		ct = self.conf.get(u'talkers:_%s'%dat.nick,'0:%s'%dat.nick).split(':',1)
		self.conf['talkers:_%s'%dat.nick] = '%s:%s'%(safe_int(ct[0])+1,ct[1])
##		## Кик уж сильно болтающих юзерей
##		if not self.is_superAdmin(jid) and not self.is_Admin(jid):
##			name = '%s/%s'%(dat.addr,dat.nick)
##			current_count,current_fraze = self.kick.get(name,[0,''])
##			dt = dat.text.lower()
##			if dt[-1*len(current_fraze):]== current_fraze and len(current_fraze)>3: current_count += 1
##			fc = safe_int(self.vars['flood_kick'])
##			if fc>0 and current_count >= fc:
##				dat.com.kick(dat.addr,dat.nick,self.vars['flood_message'])
##				del self.kick[name]
##			self.kick[name] = current_count,dt
		## Вывод данных
		if self.verifySpam(dat.text):
			dat.com.kick(dat.addr,dat.nick) ## Киляем сволочь !!!!
			return 
		if self.is_Mute(dat,dat.addr): return ## Этот канал сразу замучен - выходим
		if self.is_Blocked(dat.jid): return ## Сообщения этого юзера заблочены
		for x in self.conf.sections():
			if self.conf.get('%s:nick'%x):
				if x != dat.addr and not self.is_Mute(dat,x):
					dat.com.chatsend(x,'<%s> %s'%(dat.nick,dat.text))

	def messageCB_list(self,dat):
		'Команда листинга'
		dic = {}
		full = dat.command_param.strip().lower()=='full'
		for key in self.users_state.keys():
			conf,nick = key.split('/',1)
			if not dic.has_key(conf): dic[conf] = []
			if (nick not in dic[conf] and nick != self.conf.get('%s:nick'%conf)) or full:
				n = nick
				if self.users_state.get(key,{'blocked':False}).get('blocked',False): n += '{B}'
				dic[conf].append(n)
		for ch,mem in dic.items():
			if (mem != [] and ch!=dat.addr) or full:
				m = ''
				if self.conf.get('%s:mute'%ch): m = '{M}'
				dat.com.chatsend(dat.addr,u'В канале <%s%s> сидят следующие личности: %s.'%(ch,m,concat(mem)))


	def messageCB_kick(self,dat):
		'Киляние юзерей'
		try: jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
		except: jid = None
		if self.is_superAdmin(jid) or self.is_Admin(jid):
			kick_nick = dat.command_param.strip().lower()
			for key in self.users_state.keys():
				conf,nick = key.split('/',1)
				if nick.lower()==kick_nick and nick != self.conf.get('%s:nick'%conf): ## Есть каго килять
					dat.com.kick(conf,kick_nick,u'Кильну-ка я тебя...')

	def messageCB_me(self,dat):
		'Вывод фраз от имени бота в канал'
		for x in self.conf.sections():
			if self.conf.get('%s:nick'%x) and x != dat.addr: dat.com.chatsend(x,dat.command_param)

	def messageCB_topic(self,dat):
		'Меняет во всех каналах топик !!!'
		for x in self.conf.sections():
			if self.conf.get('%s:nick'%x):
				dat.com.settopic(x,dat.command_param)

	def messageCB_anek(self,dat):
		'Выводит новый анекдот во все каналы'
		try:
			import urllib
			from xml.dom import minidom
			dom = minidom.parse(urllib.urlopen('http://best-aneks.com/rss.php'))
			x = dom.getElementsByTagName('item')[0]
			nd = x.getElementsByTagName('link')[0]
			br = x.getElementsByTagName('description')[0].firstChild.data.strip().replace('<br>','\n').replace('<BR>','\n')
			anek,av = '',True
			for x in br:
				if x=='<': av = False
				elif x=='>': 
					av = True
					anek+=' '
				elif av: anek+=x
			for x in self.conf.sections():
				if self.conf.get('%s:nick'%x):
					dat.com.chatsend(x,u'Анекдот: %s'%anek)
		except: dat.com.chatsend(dat.addr,u'Поломалися анекдотики...скорее на http://sys.net.ru.')

	def messageCB_bor(self,dat):
		'Выводит фразу из цитатника'
		try:
			import urllib,random
			u = urllib.urlopen('http://bash.org.ru/random').read()
			u = unicode(u,'cp1251')
			x = u.find('<div>')
			br = u[x+5:u.find('</div>',x)].strip()
			br = br.replace('<br>','\n').replace('<BR>','\n').replace('<br />','\n')
			bor,av = '',True
			for x in br:
				if x=='<': av = False
				elif x=='>': 
					av = True
					bor+=' '
				elif av: bor+=x
			bor = bor.replace('&quot;','"')
			bor = bor.replace('&lt;','<')
			bor = bor.replace('&gt;','>')

			for x in self.conf.sections():
				if self.conf.get('%s:nick'%x):
					dat.com.chatsend(x,u'БОР: %s'%bor)
		except: dat.com.chatsend(dat.addr,u'Поломался цитатник...скорее на http://sys.net.ru.')

	def messageCB_ostrie(self,dat):
		'Анекдоты с острия'
		try:
			import urllib,random
			u = urllib.urlopen('http://wap.ostrie.ru').read()
			u = unicode(u,'koi8-r')
			x = u.find('<p>')
			x = u.find('<p>',x+1)
			x = u.find('<p>',x+1)
			y = u.find('</p>',x)
			if x<5 or y<x: return
			br = u[x:y].strip()
			br = br.replace('<br>','\n').replace('<BR>','\n').replace('<br />','\n').replace('<br/>','\n')
			bor,av = '',True
			for x in br:
				if x=='<': av = False
				elif x=='>': 
					av = True
					bor+=' '
				elif av: bor+=x
			bor = bor.replace('&quot;','"')
			bor = bor.replace('&lt;','<')
			bor = bor.replace('&gt;','>')

			for x in self.conf.sections():
				if self.conf.get('%s:nick'%x):
					dat.com.chatsend(x,u'Острие: %s'%skip_space_line(unescape(bor)))
		except: dat.com.chatsend(dat.addr,u'Поломалося острие...скорее на http://sys.net.ru.')


	def messageCB_fomenko(self,dat):
		'Выводит крылатую фразу фоменко'
		try:
			import urllib
			u = urllib.urlopen('http://fomenko.ru/foma/lenta/text.html').read()
			u = unicode(u,'cp1251')
			x = u.find('<b>')
			br = u[x+3:u.find('</b>',x)].strip()
			br = br.replace('<br>','\n').replace('<BR>','\n').replace('<br />','\n')
			bor,av = '',True
			for x in br:
				if x=='<': av = False
				elif x=='>': 
					av = True
					bor+=' '
				elif av: bor+=x
			bor = bor.replace('&quot;','"')
			bor = bor.replace('&lt;','<')
			bor = bor.replace('&gt;','>')

			for x in self.conf.sections():
				if self.conf.get('%s:nick'%x):
					dat.com.chatsend(x,u'Фоменко: %s'%bor)
		except: dat.com.chatsend(dat.addr,u'Поломался Фоменко...скорее на http://sys.net.ru.')

	tr_locales = ['er','re']
	def messageCB_tr(self,dat):
		'OnLine переводчик'
		try:
			import urllib
			pr = dat.command_param.strip().split(' ',1)
			if pr[0].lower() in self.tr_locales:
				fraze = urllib.quote(pr[1].encode('cp1251'))
				u = urllib.urlopen('http://pda.translate.ru/default.asp?source=%s&direction=%s&lang=ru&status=translate'%(fraze,pr[0])).read()
				u = unicode(u,'cp1251')
				x = u.find('readonly="" style="width:220px;background:#f0f0f0;">')
				br = u[x+52:u.find('</textarea>',x)].strip()
				br = br.replace('&lt;','<')
				br = br.replace('&gt;','>')
				dat.com.chatsend(dat.addr,u'Перевод: %s => %s.'%(pr[1],br))
			else: dat.com.chatsend(dat.addr,u'Я могу транслировать только из русского в энглицкий и обратно.')
		except: dat.com.chatsend(dat.addr,u'Поломался переводчик...скорее на http://sys.net.ru.')


	def messageCB_pogoda(self,dat):
		'Выводит новый погоду во все каналы'
		try:
			import urllib
			from xml.dom import minidom
			## Вычисление города
			xx = urllib.quote(dat.command_param.encode('cp1251'))
			u = urllib.urlopen('http://search.gismeteo.ru/?town=%s&req=findtown'%xx)
			dd = u.read()
			x = dd.find('http://www.gismeteo.ru/towns/')
			idx = dd[x:dd.find('.htm',x)].split('/')[-1].strip()
			if idx:
				ret = u'Погода:\n'
				r = urllib.urlopen('http://informer.gismeteo.ru/rss/%s.xml'%idx)
				dom = minidom.parse(urllib.urlopen('http://informer.gismeteo.ru/rss/%s.xml'%idx))
				for x in dom.getElementsByTagName('item'):
					ret += '%s: %s\n'%(x.getElementsByTagName('title')[0].firstChild.data.strip(),x.getElementsByTagName('description')[0].firstChild.data.strip())
				dat.com.chatsend(dat.addr,ret)
			else: dat.com.chatsend(dat.addr,u'Не могу найти запрошенный город, праверьте правильность написания.')
		except: dat.com.chatsend(dat.addr,u'Сломалась погодка...скорее на http://sys.net.ru.')


	def messageCB_talkers(self,dat):
		'Ну скока заталкил'
		da = []
		for x,y in self.conf.section(u'talkers').items():
			sp = y.split(':',1)
			da.append((safe_int(sp[0]),x,sp[1]))
		da.sort()
		da.reverse()
		r = u'Балтуны в канале:\n'
		for x in da[:10]:
			r += u'%s : %s\n'%(x[2],x[0])
		dat.com.chatsend(dat.addr,r)


	def messageCB_help(self,dat):
		'Помощь'
		dat.com.privatesend(dat.addr,dat.nick,HELP+ADDONS)

	def messageCB_help_admin(self,dat):
		'Помощь админская'
		dat.com.privatesend(dat.addr,dat.nick,ADMIN_HELP+ADDONS)

	def messageCB_changelog(self,dat):
		'Лист изменений'
		ch,st = '',False
		for x in CHANGELOG.split('\n'):
			if len(x)==0: pass
			elif not st and x[0]=='\t': st = True
			elif st and x[0]!='\t': break
			else: ch += '%s\n'%x
		dat.com.privatesend(dat.addr,dat.nick,ch+ADDONS)

	def messageCB_changelog_all(self,dat):
		'Лист ВСЕХ изменений'
		jid = self.users_state[dat.jid]['user_jid'].split('/')[0]
		if self.is_superAdmin(jid) or self.is_Admin(jid): dat.com.privatesend(dat.addr,dat.nick,CHANGELOG+ADDONS)

	def messageCB_vcard(self,dat):
		'Получение vCard'
		if not dat.command_param:
			dat.com.vcard(dat.jid,'JBL:VCARD:%s'%dat.addr)
		else:
			is_finded = False
			find_nick = dat.command_param.lower()
			for key in self.users_state.keys():
				conf,nick = key.split('/',1)
				if nick.lower() == find_nick:
					dat.com.vcard(key,'JBL:VCARD:%s'%dat.addr)
					is_finded = True
			if not is_finded: dat.com.chatsend(dat.addr,u'Человек в ником "%s" не найден ни в одной конфе :('%dat.command_param)

	def messageCB_ping(self,dat):
		'Посылаем ping'
		if not dat.command_param:
			dat.com.ping(dat.jid,'JBL:PING:%s:%s'%(time.time(),dat.addr))
		else:
			for key in self.users_state.keys():
				conf,nick = key.split('/',1)
				if nick.lower() == dat.command_param.lower():
					dat.com.ping(key,'JBL:PING:%s:%s'%(time.time(),dat.addr))

	def messageCB_mute(self,dat):
		'Посылаем mute'
		if self.conf.get('%s:mute'%dat.addr):
			del self.conf['%s:mute'%dat.addr] ## Снять запрет болтушки
			dat.com.chatsend(dat.addr,'MUTE OFF')
		else:
			self.conf['%s:mute'%dat.addr] = time.time()
			dat.com.chatsend(dat.addr,'MUTE ON')

	def messageCB_block(self,dat):
		'Блокируем свой ник от обчания с другими'
		is_blocked = self.users_state.get(dat.jid,{'blocked':False}).get('blocked',False)
		if is_blocked:
			dat.com.chatsend(dat.addr,u'Пользователь "%s" разблокировал свой ник'%dat.nick)
			del self.users_state[dat.jid]['blocked']
		else:
			dat.com.chatsend(dat.addr,u'Пользователь "%s" заблокировал свой ник'%dat.nick)
			self.users_state[dat.jid]['blocked'] = True

	def messageCB_status(self,dat):
		'Получить статутс пользотвалея'
		if dat.command_param: find_nick = dat.command_param.lower()
		else: find_nick = dat.nick
		for key in self.users_state.keys():
			kf = key.split('/')[-1]
			if kf.lower() == find_nick.lower(): # Нашли юзера
				try: status = self.users_state[key]['status']
				except: status = u'неизвестен'
				if not status: status = u'неизвестен'
				dat.com.chatsend(dat.addr,u'Статус для пользователя "%s" установлен в "%s"'%(find_nick,status))

	def presenceCB(self,sess,pres):
		#print pres
		text=''
		## Получим данные о сообщении
		dat = cInfo(pres,sess,self.vars)
		## Обработка ошибок
		if dat.type=='error':
			code = -1
			for x in pres.getChildren():
				if x.getName()=='error': code = x.getAttr('code')
			if code=='409': ## Конфликт ников
				self.conf['%s:nick'%dat.addr] = self.conf['%s:nick'%dat.addr] + '_'
				self.confJoin(dat.addr)
		## Создадим словарь со всеми настройками юзера
		if  dat.jid and not self.users_state.has_key(dat.jid): 
			self.users_state[dat.jid] = {}
			text=dat.nick+u' пришёл в'
		self.users_state[dat.jid]['user_jid'] = pres.getJid()
		## Если достунен статус - запомним его
		if dat.status: self.users_state[dat.jid]['status'] = dat.status
		## Реконект к чату
		if dat.type=='unavailable' and self.conf.get('%s:nick'%dat.addr) == dat.nick:
			self.confJoin(dat.addr)
			sess.send(self.presence[dat.addr])
		## Выход юзера
		if dat.type=='unavailable':
			if dat.jid in self.users_state.keys():
				text=dat.nick+u' покинул'
				del self.users_state[dat.jid]
		## Вывод всего на печать
		if text:
			if safe_int(self.conf.get('%s:connect_time'%dat.addr,0))+20<time.time():
				for x in self.conf.sections():
					if self.conf.get('%s:nick'%x): ## Это описание конфига
						if x != dat.addr and dat.nick!=self.conf['%s:nick'%x] and not self.is_Mute(dat,x):
							dat.com.chatstatus(x,u'%s %s'%(text,dat.addr))
							#dat.com.chatsend(x,u'%s %s'%(text,dat.addr))
			LOG(pres,dat.nick,text)

	def iqCB(self,sess,pres):
		'Обработка ответов от сервера'
		dat = cInfo(pres,sess)
		if dat.command_id == u'ping': self.iqCB_ping(dat,sess,pres)
		elif dat.command_id == u'vcard': self.iqCB_vcard(dat,sess,pres)

	def iqCB_ping(self,dat,sess,pres):
		'Выводит результат пинга на юзера'
		t,to = dat.command_id_param
		tm = time.time() - float(t)
		dat.com.chatsend(to,u'Пинг до "%s" идет ровно %s секунд.'%(dat.nick,tm))

	def iqCB_vcard(self,dat,sess,pres):
		'Выводит результаты данных vcard на юзера'
		ret = u'Информация о пользователе: %s который сидит в %s.\n'%(dat.nick,dat.addr)
		dic = {}
		try:
			cld = pres.getChildren()[0]
			for x in cld.getChildren():
				dic[x.getName()] = (x.getData(),x.getChildren())
			if dic.has_key('FN'): ret += u'Полное имя:%s\n'%dic['FN'][0]
			if dic.has_key('BDAY'): ret += u'Дата рождения:%s\n'%dic['BDAY'][0]
			if dic.has_key('NICKNAME'): ret += u'Любимый ник:%s\n'%dic['NICKNAME'][0]
			if dic.has_key('URL'): ret += u'Сайт:%s\n'%dic['URL'][0]
			if dic.has_key('EMAIL'):
				ret += u'Почтовые адреса: '
				if dic['EMAIL'][0]!='': ret += '%s,'%dic['EMAIL'][0]
				for y in dic['EMAIL'][1]:
					if y.getName()=='USERID': ret += '%s,'%y.getData()
				ret = ret [:-1].strip()+'\n'
			if dic.has_key('DESC'): ret += u'Отсебятина:\n%s\n'%dic['DESC'][0].strip()
			ret += '\n'
			dat.com.chatsend(dat.command_id_param[0],ret.strip())
		except: pass



##	def iqCB__old(self,sess,pres):
##		'Отработка команды LIST' ## ПОКА НЕ УДАЛЯТЬ - МНОГО ИНТЕРЕСНОГО !!!
##		dat = cInfo(pres,sess)
##		id = pres.getID()
##		conference = u'%s'%pres.getFrom()
##		nick=pres.getFrom().getResource()
##		if id[:9] == 'JBL:LIST:': ## Листинг другой конфы
##			try: my_nick = CONFIG['CHANNELS'][conference]['nick'] # Мой ник в этой конфе
##			except: return
##			to = id[9:]
##			members = '<LIST %s> '%conference
##			for x in pres.getQueryChildren():
##				nick = x.getAttr('jid').split('/')[-1]
##				if nick != my_nick: members += '%s,'%nick
##			sess.send(protocol.Message(to,members[:-1],typ='groupchat'))
##		elif id[:15] == 'JBL:LIST2VCARD:': ## Получение листингов пользователей для получения vCard
##			to,find_nick = id[15:].split(':',1)
##			for x in pres.getQueryChildren():
##				nick = x.getAttr('jid').split('/')[-1]
##				if nick.lower()==find_nick.lower(): sess.send("<iq to='%s/%s' type='get' id='JBL:VCARD:%s'><vCard xmlns='vcard-temp'/></iq>"%(conference,nick,to))
##		elif id[:14] == 'JBL:LIST2PING:': ## Получение листингов пользователей для получения vCard
##			to,find_nick = id[14:].split(':',1)
##			for x in pres.getQueryChildren():
##				nick = x.getAttr('jid').split('/')[-1]
##				if nick.lower()==find_nick.lower(): sess.send("<iq to='%s/%s' type='get' id='JBL:PING:%s:%s'><query xmlns='jabber:iq:version'/></iq>"%(conference,nick,time.time(),to))
##		elif id[:16] == 'JBL:LIST2STATUS:': ## Получение статуса
##			to,find_nick = id[16:].split(':',1)
##			for x in pres.getQueryChildren():
##				nick = x.getAttr('jid').split('/')[-1]
##				if nick.lower()==find_nick.lower(): sess.send("<iq to='%s/%s' type='get' id='JBL:STATUS:%s'><query xmlns='jabber:iq:last'/></iq>"%(conference,nick,to))
##		elif id[:11] == 'JBL:STATUS:': ## Статус юзера
##			to = id[11:]
##			print unicode(pres).encode('utf-8')
##			try: sess.send(protocol.Message(to,u'Статус для "%s" установлен в "%s"'%(nick,pres.getQueryPayload()[0]),typ='groupchat'))
##			except: sess.send(protocol.Message(to,u'Статус для "%s" неизвестен'%nick,typ='groupchat'))
##		elif id[:9] == 'JBL:PING:': ## Пинг от юзера
##			t,to = id[9:].split(':',1)
##			tm = time.time() - float(t)
##			sess.send(protocol.Message(to,u'Пинг до "%s" идет ровно %s секунд.'%(nick,tm),typ='groupchat'))
##		elif id[:10] == 'JBL:VCARD:': ## Получения vCard от пользователя
##			to = id[10:]
##			ret = u'Информация о пользователе: %s который сидит в %s.\n'%(nick,conference.split('/')[0])
##			dic = {}
##			#print u'---------\n%s\n-----------\n'%pres
##			try:
##				cld = pres.getChildren()[0]
##				for x in cld.getChildren():
##					dic[x.getName()] = (x.getData(),x.getChildren())
##				if dic.has_key('FN'): ret += u'Полное имя:%s\n'%dic['FN'][0]
##				if dic.has_key('BDAY'): ret += u'Дата рождения:%s\n'%dic['BDAY'][0]
##				if dic.has_key('NICKNAME'): ret += u'Любимый ник:%s\n'%dic['NICKNAME'][0]
##				if dic.has_key('URL'): ret += u'Сайт:%s\n'%dic['URL'][0]
##				if dic.has_key('EMAIL'):
##					ret += u'Почтовые адреса: '
##					if dic['EMAIL'][0]!='': ret += '%s,'%dic['EMAIL'][0]
##					for y in dic['EMAIL'][1]:
##						if y.getName()=='USERID': ret += '%s,'%y.getData()
##					ret = ret [:-1]+'\n'
##				if dic.has_key('DESC'): ret += u'Отсебятина:\n%s\n'%dic['DESC'][0]
##				ret += '\n'
##				sess.send(protocol.Message(to,ret,typ='groupchat'))
##			except: pass


def procedure(CONFIG):
	'Основная процедура'
	## Процедура присоединения к серверу
	bot = cl_dotBot(CONFIG)
	bot.connect()
	bot.reactor()


#CONFIG=loadConfig()
CONFIG = Config()
CONFIG.set_default(DEFAULT_CFG)
CONFIG.open('dotBot.cnf')
import atexit
atexit.register(CONFIG.save)
#CONFIG['PRESENCE'] = {}
#LOG = CLASS_LOG(CONFIG['GLOBAL']['log_folder'],CONFIG['GLOBAL']['log_to_screen'].strip()=='1')
LOG = CLASS_LOG(CONFIG['GLOBAL:log_folder'],CONFIG['GLOBAL:log_to_screen'].strip()=='1')
procedure(CONFIG)
CONFIG.save()

